import random
import math
import pyglet
import data
import debris

class Trawler:
    """An evil little boat up to no good, sir"""

    TRAWLER_TIMER = 2 # second til trawler appears
    TRAWLER_SPEED = 150
    TRAWLER_START_DISTANCE = 3
    TRAWLER_BOTTOM = 0.72
    TRAWLER_SINKAGE = 0.13
    SEASICKNESS = 2.0
    SWELL = 0.05
    PITCH_FREQ = 1.3
    PITCH_ANGLE = 2.0
    DEBRIS_BASE_IVAL = 2.0 # baseline avg seconds between debris launches
    DEBRIS_IVAL_DECREASE = 0.005 # amount avg interval decreases per second of play
    DEBRIS_MIN_IVAL = 0.5 # Minimum seconds between debris launches

    def __init__(self, game):
        self.game = game
        trawler_img = data.image('trawler-left.png')
        trawler_img.anchor_x = trawler_img.width / 2
        trawler_img.anchor_y = 0
        left_sprite = pyglet.sprite.Sprite(trawler_img)
        trawler_img = data.image('trawler-right.png')
        trawler_img.anchor_x = trawler_img.width / 2
        trawler_img.anchor_y = 0
        right_sprite = pyglet.sprite.Sprite(trawler_img)
        self.sprites = {-1: left_sprite, 1: right_sprite}
        self.trawler_timer = self.TRAWLER_TIMER
        self.left_max = -trawler_img.width
        self.right_max = game.width + trawler_img.width
        self.time = 0
        self.debris_offset_x = trawler_img.width / 3
        self.debris_offset_y = trawler_img.height / 2
        self.next_debris_time = 0
        # use separate audio player so we can tweak volume
        self.player = pyglet.media.Player()
        self.player.play()

    def spoil_the_party(self):
        """Enter the trawler to spoil the fun"""
        self.distance = self.TRAWLER_START_DISTANCE
        self.direction = random.choice((-1, 1))
        self.set_sprite()
        self.player.volume = 0.25
        self.player.queue(data.sound('ferry_fog_horn.mp3'))

    def set_sprite(self):
        """Setup the trawler sprite"""
        self.trawler_sprite = self.sprites[self.direction]
        self.trawler_sprite.scale = 1.0 / self.distance
        self.trawler_sprite.opacity = self.trawler_sprite.scale * 200 + 55
        if self.direction > 0:
            self.trawler_sprite.x = -self.trawler_sprite.width
        else:
            self.trawler_sprite.x = self.game.width + self.trawler_sprite.width
        self.trawler_sprite.y = (
            self.game.height * self.TRAWLER_BOTTOM 
            - self.trawler_sprite.height * self.TRAWLER_SINKAGE)
        self.speed = self.direction * self.TRAWLER_SPEED / self.distance

    def close_in(self):
        """Move closer and reverse direction"""
        if self.distance > 1:
            self.distance -= 1
            self.direction = -self.direction
            self.set_sprite()
            self.player.volume *= 2
            self.player.queue(data.sound('ferry_fog_horn.mp3'))
        else:
            # We'll be back, muhahahaha!
            self.trawler_timer = self.TRAWLER_TIMER
    
    def update(self, dt):
        self.time += dt
        if self.trawler_timer > 0:
            self.trawler_timer -= dt
            if self.trawler_timer <= 0:
                self.spoil_the_party()
        else:
            self.trawler_sprite.x += self.speed * dt
            self.trawler_sprite.rotation = math.sin(
                self.time * self.PITCH_FREQ) * self.PITCH_ANGLE
            self.trawler_sprite.y -= math.sin(
                self.time * self.SEASICKNESS) * self.trawler_sprite.height * self.SWELL * dt
            if ((self.speed > 0 and self.trawler_sprite.x > self.right_max)
                or (self.speed < 0 and self.trawler_sprite.x < self.left_max)):
                self.close_in()
            if self.distance == 1:
                debris_x = self.trawler_sprite.x - self.direction * self.debris_offset_x
                debris_y = self.trawler_sprite.y + self.debris_offset_y
                if (self.next_debris_time and self.time > self.next_debris_time
                    and debris_x > 0 and debris_x < self.game.width):
                    # pitch some debris off the stern
                    debris.DebrisSprite(self.game, debris_x, debris_y, -self.direction)
                    data.sound('boing.mp3').play()
                    self.next_debris_time = 0
                if not self.next_debris_time:
                    interval = max(
                        self.DEBRIS_BASE_IVAL - self.DEBRIS_IVAL_DECREASE * self.time,
                        self.DEBRIS_MIN_IVAL)
                    self.next_debris_time = self.time + random.expovariate(1.0 / interval)
            
    def draw_distant(self):
        """Draw the trawler if it's far away"""
        if self.trawler_timer <= 0 and self.distance > 1:
            self.trawler_sprite.draw()

    def draw_close(self):
        """Draw the trawler if it's close"""
        if self.trawler_timer <= 0 and self.distance == 1:
            self.trawler_sprite.draw()


